package com.weilele.mvvm.utils.activity


import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityManager
import android.content.ComponentName
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.content.res.TypedArray
import android.graphics.Point
import android.net.Uri
import android.os.Build
import android.os.Looper
import android.view.View
import android.view.Window
import android.view.WindowInsets
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.Toast
import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import com.ut.device.UTDevice
import com.weilele.mvvm.*
import com.weilele.mvvm.base.MvvmActivity
import com.weilele.mvvm.base.helper.appCompatActivity
import com.weilele.mvvm.base.helper.logStackTrace
import com.weilele.mvvm.utils.isThis
import com.weilele.mvvm.utils.permission.callPermissions
import com.weilele.mvvm.utils.safeGet
import com.weilele.mvvm.utils.tryError
import java.util.*
import kotlin.system.exitProcess

/**
 * 在对话框里面的context是ContextWrapper
 * 所以提供一个方法，将context转化为activity
 */
inline fun <reified T : Activity> Context?.toActivity(): T? {
    this ?: return null
    return if (this !is Activity && this is ContextWrapper) {
        baseContext.safeGet()
    } else {
        this.safeGet()
    }
}

/**
 * 回到桌面，不退出app
 */
fun Context.goHome() {
    tryError {
        val home = Intent(Intent.ACTION_MAIN)
        home.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
        home.addCategory(Intent.CATEGORY_HOME)
        startActivity(home)
    }
}

/**
 * 跳转到浏览器
 */
fun Context.goToWeb(url: String) {
    tryError {
        val uri = Uri.parse(url)
        val intent = Intent(Intent.ACTION_VIEW, uri)
        startActivity(intent)
    }
}

/**
 * 系统分享
 */
fun Context.goToShare(title: String, text: String) {
    tryError {
        var shareIntent = Intent()
        shareIntent.action = Intent.ACTION_SEND
        shareIntent.type = "text/plain"
        shareIntent.putExtra(Intent.EXTRA_TEXT, text)
        //切记需要使用Intent.createChooser，否则会出现别样的应用选择框，您可以试试
        shareIntent = Intent.createChooser(shareIntent, title)
        startActivity(shareIntent)
    }
}

/**
 * 打电话
 * 需要[Manifest.permission.CALL_PHONE]权限
 */
@SuppressLint("MissingPermission")
fun MvvmActivity.goCallPhone(number: String) {
    callPermissions(mutableListOf(android.Manifest.permission.CALL_PHONE)) {
        if (it.isEmpty()) {
            val intent = Intent(Intent.ACTION_CALL)
            val data = Uri.parse("tel:$number")
            intent.data = data
            startActivity(intent)
        } else {
            logE("打电话权限被拒绝")
        }
    }
}

/**
 * 利用阿里云库获取设备唯一标识，
 * 建议优先使用这个方法获取设备id
 */
fun getUtdId(): String? {
    return UTDevice.getUtdid(app)
}

/**
 * 设置窗口的透明度
 */
fun Activity.setWindowAlpha(bgAlpha: Float) {
    window.setWindowAlpha(bgAlpha)
}

/**
 * 设置窗口的透明度
 */
fun Window?.setWindowAlpha(bgAlpha: Float) {
    this ?: return
    val lp = attributes
    if (lp.alpha != bgAlpha) {
        lp.alpha = bgAlpha //0.0-1.0
        attributes = lp
    }
}

/**
 * 结束所有app
 */
fun Context.finishAllActivity(isForeClose: Boolean = false) {
    val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    am.appTasks?.forEach {
        it.finishAndRemoveTask()
    }
    if (isForeClose) {
        exitProcess(-1)
    }
}

/**
 * 结束所有app
 */
fun finishAllActivityByList(isForeClose: Boolean = false) {
    activityList.forEach {
        it.finish()
    }
    if (isForeClose) {
        exitProcess(-1)
    }
}

/**
 * 结束某些activity
 */
fun finisSomeActivity(vararg cls: Class<*>) {
    activityList.forEach { activity ->
        cls.forEach { cls ->
            if (activity.javaClass == cls) {
                activity.finishAfterTransition()
            }
        }
    }
}

/**
 * back一些activity正常情况和finisSomeActivity效果一样
 * 推荐优先用这个，会处理回退栈和动画效果
 */
fun backPressedSomeActivity(vararg cls: Class<*>) {
    activityList.forEach { activity ->
        cls.forEach { cls ->
            if (activity.javaClass == cls) {
                activity.onBackPressed()
            }
        }
    }
}

/**
 * 代码运行在主线程
 */
fun runOnUiThread(run: Runnable): Runnable {
    if (isMainThread()) run.run() else mainHandler.post(run)
    return run
}

/**
 * 代码延时运行
 */
fun runOnUiDelayed(delay: Long = 0L, run: Runnable): Runnable {
    if (delay <= 0) {
        runOnUiThread(run)
    } else {
        mainHandler.postDelayed(run, delay)
    }
    return run
}

/**
 * 是否是主线程
 */
fun isMainThread() = Looper.getMainLooper() === Looper.myLooper()

/**
 * toast
 */
fun CharSequence?.toast(duration: Int = Toast.LENGTH_SHORT, default: String? = "未知消息") {
    if (this?.contains("job", true) == true) {
        logStackTrace(this.toString())
    }
    runOnUiThread {
        Toast.makeText(app, this@toast ?: default, duration).show()
    }
}

/**
 * toast
 * 这里只能是string中的资源文件
 */
fun Int?.toast(duration: Int = Toast.LENGTH_SHORT, default: String? = "未知消息") {
    var charSequence: CharSequence? = null
    if (this != null) {
        tryError {
            charSequence = getResString(this)
        }
    }
    charSequence.toast(duration, default)
}

/**
 * 隐藏键盘
 */
fun Activity?.hiddenKeyboard() {
    this ?: return
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        window.decorView.windowInsetsController?.hide(WindowInsets.Type.ime())
    } else {
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
        val focusView = window.decorView.findFocus()
        if (imm != null && focusView != null) {
            imm.hideSoftInputFromWindow(focusView.windowToken, 0)
        }
    }
}

fun DialogFragment?.hiddenKeyboard() {
    this ?: return
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        dialog?.window?.decorView?.windowInsetsController?.hide(WindowInsets.Type.ime())
    } else {
        val imm =
                appCompatActivity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
        val focusView = dialog?.window?.decorView?.findFocus()
        if (imm != null && focusView != null) {
            imm.hideSoftInputFromWindow(focusView.windowToken, 0)
        }
    }
}

/**
 * 显示键盘
 */
fun Activity?.showKeyboard(focusView: View?, selectionEnd: Boolean = true) {
    this ?: return
    focusView ?: return
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
        focusView.windowInsetsController?.show(WindowInsets.Type.ime())
    } else {
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
        focusView.requestFocus()
        imm?.showSoftInput(focusView, 0)
    }
    if (selectionEnd) {
        focusView.isThis<EditText> {
            this.setSelection(this.text.count())
        }
    }
}

fun Activity?.showKeyboardPost(focusView: View?, isOutsideHide: Boolean = true) {
    this ?: return
    focusView ?: return
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        showKeyboard(focusView, isOutsideHide)
    } else {
        focusView.post { showKeyboard(focusView, isOutsideHide) }
    }
}


/**
 * 从哪个界面按的home，点击通知栏，进入哪个界面
 */
fun Context.getLastActivityIntent(): Intent {
    val appIntent = Intent()
    if (activityList.isNotEmpty()) {
        val topActivity = activityList[activityList.size - 1]
        appIntent.component = ComponentName(
                this.packageName,
                this.packageName + "." + topActivity.localClassName
        )
    }
    //关键的一步，设置启动模式
    appIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
    return appIntent
}

/**
 * 获取屏幕尺寸
 * isOnlyDisplay:true 不计算状态栏
 */
fun Activity.getScreenSize(isOnlyDisplay: Boolean = false): Point {
    return window.getScreenSize(isOnlyDisplay)
}

/**
 * 获取屏幕尺寸
 * isOnlyDisplay:true 不计算状态栏
 */
fun Window.getScreenSize(isOnlyDisplay: Boolean = false): Point {
    val point = Point()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        val metrics = windowManager.currentWindowMetrics
        val bounds = metrics.bounds
        if (isOnlyDisplay) {
            val windowInsets = metrics.windowInsets
            val insets =
                    windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars() or WindowInsets.Type.displayCutout());
            val insetsWidth = insets.right + insets.left
            val insetsHeight = insets.top + insets.bottom
            //需要减去状态栏和导航栏高度
            point.x = bounds.width() - insetsWidth
            point.y = bounds.height() - insetsHeight
        } else {
            point.x = bounds.width()
            point.y = bounds.height()
        }
    } else {
        if (isOnlyDisplay) {
            windowManager.defaultDisplay.getSize(point)
        } else {
            windowManager.defaultDisplay?.getRealSize(point)
        }
    }
    return point
}

/**
 * 是否竖屏
 */
fun Resources.isScreenPortrait(): Boolean {
    return displayMetrics.widthPixels < displayMetrics.heightPixels
}

/**
 * 是否竖屏
 */
fun View.isScreenPortrait(): Boolean {
    return resources.isScreenPortrait()
}

/**
 * 是否竖屏
 */
fun Activity.isScreenPortrait(): Boolean {
    return resources.isScreenPortrait()
}

/**
 * 读取assets的文件
 */
fun Context.readAssetsFileToText(fileName: String?): String? {
    fileName ?: return null
    return try {
        val reader = assets.open(fileName).bufferedReader()
        val text = reader.readText()
        reader.close()
        text
    } catch (e: Throwable) {
        e.printStackTrace()
        null
    }
}

/**
 * 读取assets的文件
 * 转换为对象
 */
inline fun <reified T> Context.readAssetsFileFromJson(fileName: String?): T? {
    val text = readAssetsFileToText(fileName) ?: return null
    return try {
        gson.fromJson<T>(text, T::class.java)
    } catch (e: Throwable) {
        e.printStackTrace()
        null
    }
}

/**
 * 代码获取attr
 * 例如：xml中我们这样写         android:background="?selectableItemBackground"
 *  代码中   context.getAttrValue(intArrayOf(R.attr.selectableItemBackground)){
 *          it.getDrawable(R.attr.selectableItemBackground)
 *          }
 */

fun Context.getAttrValue(
        attrsArray: IntArray,
        onGetTypeArray: Function3<
                @ParameterName("typedArray") TypedArray,
                @ParameterName("attr") Int,
                @ParameterName("index") Int,
                Unit>
) {
    val typedArray: TypedArray = obtainStyledAttributes(attrsArray)
    if (MvvmConf.IS_DEBUG && attrsArray.count() != typedArray.indexCount) {
        error("Assertion failed")
    }
    repeat(attrsArray.count()) {
        onGetTypeArray.invoke(typedArray, attrsArray[it], it)
    }
    typedArray.recycle()
}

/**
 * 保持屏幕常亮
 */
fun Window?.keepScreenOn(keep: Boolean) {
    this ?: return
    if (keep) {
        addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    } else {
        clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }
}

/**
 * 保持屏幕常亮
 */
fun Activity?.keepScreenOn(keep: Boolean) {
    this?.window?.keepScreenOn(keep)
}

/**
 * 保持屏幕常亮
 */
fun Fragment?.keepScreenOn(keep: Boolean) {
    this?.appCompatActivity?.window?.keepScreenOn(keep)
}

/**
 * 获取fragment
 */
inline fun <reified T> AppCompatActivity?.findFragmentById(@IdRes id: Int?): T? {
    id ?: return null
    return this?.supportFragmentManager?.findFragmentById(id).safeGet()
}

/**
 * 获取fragment
 */
inline fun <reified T> Fragment?.findChildFragmentById(@IdRes id: Int?): T? {
    id ?: return null
    return this?.childFragmentManager?.findFragmentById(id).safeGet()
}

/**
 * 获取fragment
 */
inline fun <reified T> Fragment?.findFragmentById(@IdRes id: Int?): T? {
    id ?: return null
    return this?.parentFragmentManager?.findFragmentById(id).safeGet()
}

/**
 * 是否为夜间模式
 */
fun Resources.isUiNightModel(): Boolean {
    val nightModeFlags: Int = configuration.uiMode and
            Configuration.UI_MODE_NIGHT_MASK
//    when (nightModeFlags) {
//        Configuration.UI_MODE_NIGHT_YES,
//        Configuration.UI_MODE_NIGHT_NO,
//        Configuration.UI_MODE_NIGHT_UNDEFINED -> {
//        }
//    }
    return nightModeFlags == Configuration.UI_MODE_NIGHT_YES
}

/**
 * 是否为夜间模式
 */
fun Activity.isUiNightModel(): Boolean {
    return resources.isUiNightModel()
}

/**
 * 是否为夜间模式
 */
fun View.isUiNightModel(): Boolean {
    return resources.isUiNightModel()
}

/**
 * 设置为夜间模式
 * isNightMode null, 代表模式自动
 */
fun AppCompatActivity.setUiNightModel(isNightMode: Boolean?, canReCreate: Boolean = true) {
    if (isNightMode == null) {
        delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
        if (canReCreate) {
            recreate()
        }
        return
    }
    if (isNightMode) {
        delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES
    } else {
        delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_NO
    }
    if (canReCreate) {
        recreate()
    }
}

